import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.border.EmptyBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.JTextField;

import java.awt.Color;

import javax.swing.JLabel;
import javax.swing.ImageIcon;

import aurelienribon.tweenengine.Tween;
import aurelienribon.tweenengine.TweenManager;
import aurelienribon.tweenengine.equations.Quint;

import java.awt.Font;


import java.util.ArrayList;


public class GuiManager extends JFrame {

  private JPanel mainPanel;
  private JTextArea displayHeaderArea;
  private JTextArea displayScreenArea;
  private JTextField commandTextField;
  private JLabel feedBackText;
  
  private final boolean BORDER_OFF = true;
  
  private final String FINISH = "FINISH";
  private final String NOTFINISH = "NOTFINISH";
  private final String NOTHING = "";
  private final String SPLIT = ",";
  private final String HASHTAG = "#";
  private final String LEVELTAG = "LvL";
  private final String STRING_DISPLAY_FORMAT = "%1s%2d.  %3s \t\t\t\t %4s\t%5s%6s %7s\n";
  
  private String taskTitle;
  private String taskTime;
  private String taskTag;
  private String taskIsFinish;
  private String taskUrgencyLevel;
   
  private ArrayList<String> userInputHistory = new ArrayList<String>();
  private int historyIndexCursor = -1;
  
  private boolean isApplicationHidden = false;
  
  private TriggerOnEnter triggerOnEnter;
  private TriggerOnTextChange triggerOnTextChange;
  private TriggerOnKeyPress triggerOnKeyPress;
  
  private AttributeHandler attributeHandler = new AttributeHandler();
  private MessageManager guiMessageBox = new MessageManager();
  private CommandManager commandManager = new CommandManager();
  private TweenManager tweenManager = new TweenManager();
  
  private JPanel outerDisplayPanel;
  private JPanel innerDisplayPanel;

  public GuiManager() {  
    setUpComponents(); 
    setUpEventHandlers();
    
    Tween.registerAccessor(Component.class, new GuiComponentAccessor());

    addWindowListener(new WindowAdapter() {
      @Override public void windowOpened(WindowEvent e) {
          new GuiDrawingCanvas() {
              @Override protected void update(int elapsedMillis) {
                  tweenManager.update(elapsedMillis);
              }
          }.start();
      }
  });
    
  }


  private void setUpEventHandlers() {
    createEventHandlers();   
    addEventHandlersToComponents();
  }


  private void addEventHandlersToComponents() {
    mainPanel.addKeyListener(triggerOnKeyPress);
    displayHeaderArea.addKeyListener(triggerOnKeyPress);
    displayScreenArea.addKeyListener(triggerOnKeyPress);
    commandTextField.addActionListener(triggerOnEnter);
    commandTextField.getDocument().addDocumentListener(triggerOnTextChange);
    commandTextField.addKeyListener(triggerOnKeyPress);
  }


  private void createEventHandlers() {
    triggerOnEnter = new TriggerOnEnter();
    triggerOnTextChange = new TriggerOnTextChange();
    triggerOnKeyPress = new TriggerOnKeyPress();
  }


  private void setUpComponents() {
    createComponents();
    setComponentsAttributes();
    addComponentsToPanel();
  }

  private void addComponentsToPanel() {
    
    outerDisplayPanel = new JPanel();
    outerDisplayPanel.setBackground(Color.WHITE);
    outerDisplayPanel.setBounds(48, 17, 773, 246);
    mainPanel.add(outerDisplayPanel);
    outerDisplayPanel.setLayout(null);
    
    innerDisplayPanel = new JPanel();
    innerDisplayPanel.setBackground(Color.WHITE);
    innerDisplayPanel.setBounds(10, 0, 753, 246);
    outerDisplayPanel.add(innerDisplayPanel);
    innerDisplayPanel.setLayout(null);
    displayHeaderArea = new JTextArea();
    displayHeaderArea.setText("All");
    displayHeaderArea.setEditable(false);
    displayHeaderArea.setBounds(10, 11, 740, 30);
    innerDisplayPanel.add(displayHeaderArea);
    displayHeaderArea.setFont(new Font("Arial", Font.BOLD, 22));
    displayScreenArea = new JTextArea();
    displayScreenArea.setColumns(20);
    displayScreenArea.setLineWrap(true);
    displayScreenArea.setRows(5);
    displayScreenArea.setWrapStyleWord(true);
    displayScreenArea.setEditable(false);
    displayScreenArea.setFont(new Font("Arial", Font.BOLD, 12));
    displayScreenArea.setBounds(10, 42, 740, 193);
    innerDisplayPanel.add(displayScreenArea);
    mainPanel.add(commandTextField);
    
    JLabel mainPanelBG = new JLabel("");
    mainPanelBG.setIcon(new ImageIcon(getClass().getResource("/resources/images/GuiManagerBG.png")));
    mainPanelBG.setBounds(10, 0, 850, 300);
    mainPanelBG.addKeyListener(triggerOnKeyPress);
    
    mainPanel.add(mainPanelBG);
    
    feedBackText = new JLabel("");
    feedBackText.setForeground(Color.WHITE);
    feedBackText.setFont(new Font("HelveticaNeueLT Pro 55 Roman", Font.PLAIN, 14));
    feedBackText.setBounds(40, 310, 430, 14);
    mainPanel.add(feedBackText);
    
    JLabel feedBackBG = new JLabel("");
    feedBackBG.setForeground(Color.WHITE);
    feedBackBG.setBounds(22, 295, 463, 44);
    feedBackBG.setIcon(new ImageIcon(getClass().getResource("/resources/images/GuiManagerFB.png")));
    
    mainPanel.add(feedBackBG);
  }


  private void setComponentsAttributes() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setContentPane(mainPanel);
    setUpBordersForGui();
    
    mainPanel.setLayout(null);
    
    commandTextField.setBounds(31, 276, 807, 19);
    commandTextField.setColumns(10);
    commandTextField.setFont(new Font("HelveticaNeueLT Pro 55 Roman", Font.PLAIN, 14));
    
    

  }


  private void setUpBordersForGui() {
    if(BORDER_OFF) {
      setBounds(100, 10, 900, 350); //Use this when removing border
      setUndecorated(true); // Removes border
      setBackground(new Color(0,0,0,0)); // Sets panel Background to Transparent
    } else {
      setBounds(100, 100, 530, 290); //WithBorder
    }
  }


  private void createComponents() {
    mainPanel = new JPanel();
    commandTextField = new JTextField();
    commandTextField.setToolTipText("Enter Commands Here");
    commandTextField.setBackground(Color.BLACK);
    commandTextField.setForeground(Color.WHITE);
    commandTextField.setCaretColor(Color.WHITE);
    commandTextField.setBorder(null);    
  }

  private class TriggerOnKeyPress implements KeyListener {
    public void keyPressed(KeyEvent keyPressed) {
      int keyCode = keyPressed.getKeyCode();
      if(keyCode == KeyEvent.VK_END) {
        System.exit(0);
      } else if(keyCode == KeyEvent.VK_UP) {      
        if(historyIndexCursor > 0) {
          historyIndexCursor--;
        }
        if(historyIndexCursor != -1) {
          commandTextField.setText(userInputHistory.get(historyIndexCursor));
        }
      } else if(keyCode == KeyEvent.VK_DOWN) {
        if(historyIndexCursor < userInputHistory.size() - 1) {
          historyIndexCursor++;
        } 
        if(historyIndexCursor != -1) {
          commandTextField.setText(userInputHistory.get(historyIndexCursor));
        }
      } else if(keyCode == KeyEvent.VK_F12) {
        hideApplication();
      } else if(keyCode == KeyEvent.VK_RIGHT) {
        Tween.to(innerDisplayPanel, GuiComponentAccessor.POSITION, 1000)
        .target(1000, 0)
        .ease(Quint.INOUT)
        .delay(10)
        .start(tweenManager);
      } else if(keyCode == KeyEvent.VK_LEFT) {
        Tween.to(innerDisplayPanel, GuiComponentAccessor.POSITION, 1000)
        .target(0, 0)
        .ease(Quint.INOUT)
        .delay(10)
        .start(tweenManager);
      }
      commandTextField.requestFocus();
    }

    public void keyReleased(KeyEvent arg0) {
    }

    public void keyTyped(KeyEvent arg0) {
    }
   }
  
  private void hideApplication() {
    if(isApplicationHidden) {
      slideDownApplication();
    } else {
      slideUpApplication();
    }
  }
  
  private class TriggerOnTextChange implements DocumentListener {
    public void changedUpdate(DocumentEvent arg0) {
    }
 
    public void insertUpdate(DocumentEvent arg0) {     
    }

    public void removeUpdate(DocumentEvent arg0) {
    }
  }

  private class TriggerOnEnter implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent event) {
      String userInputCommand = "";   
      if(event.getSource() == commandTextField) {
        
        userInputCommand = commandTextField.getText();
        userInputHistory.add(userInputCommand);
        historyIndexCursor = userInputHistory.size();
        commandManager.setUserInput(userInputCommand);
        ArrayList<String> listOfTaskToBeDisplayed = attributeHandler.convertTaskToString(commandManager.console());
        displayScreenArea.setText(NOTHING);
        int index = 1;
        for(int i = 0; i < listOfTaskToBeDisplayed.size(); i++) {
          extractAttributesFromTaskString(listOfTaskToBeDisplayed.get(i));
          displayScreenArea.append(constructStringFormat(index++)); 
        }
        
        
        feedBackText.setText(guiMessageBox.getMessageStringToGUI());

        
        
        commandTextField.setText(NOTHING);
      }
    }

    private String constructStringFormat(int index) {
      String spaceString = constructSpaceString(index);
      String taskString = constructTaskString(index, spaceString);
      return taskString;
    }
    
    private String constructTaskString(int index, String spaceString) {
      return String.format(STRING_DISPLAY_FORMAT, spaceString, index, taskTitle, taskTag, taskTime, taskUrgencyLevel, taskIsFinish);
    }

    private String constructSpaceString(int index) {
      if(index < 10) {
        return "  ";
      } 
      return NOTHING;
    }

    private void extractAttributesFromTaskString(String taskString) {
      String[] taskStringParts = taskString.split(SPLIT);
      taskTitle = taskStringParts[0];
      taskTime = taskStringParts[1];
      taskTag = addHashTag(taskStringParts[2]);
      taskUrgencyLevel = addLevelTag(taskStringParts[3]);
      taskIsFinish = taskStringParts[4];
      
    }

    private String addLevelTag(String levelString) {
      return LEVELTAG + levelString;
    }
    
    private String addHashTag(String taskTag) {
      if(!taskTag.equals(NOTHING)) {
        return HASHTAG + taskTag;
      }
      return taskTag;
    }
    
  }
  
  private void slideUpApplication() {
    for(int i = 0; i < 1000; i++) {
      setBounds(100, 10 - i/2, 900, 350);
    }  
    isApplicationHidden = true;
  }

  private void slideDownApplication() {
    for(int i = 0; i < 1000; i++) {
      setBounds(100,  i/5 - 189, 900, 350);
    }
    isApplicationHidden = false;
  }

  
  
  
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      public void run() {
        try {
          GuiManager frame = new GuiManager();
          frame.setVisible(true);
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    });
  }
}
